home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  8.7 KB  |  309 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Devices.h>
  13. #include <DriverServices.h>
  14. #include <CodeFragments.h>
  15. #include <MacTypes.h>
  16. #include <USB.h>
  17.  
  18. #ifndef DDKBuild
  19.     #include <USBPriv.h>
  20. #endif
  21.  
  22. #include "KeyboardModule.h"
  23.  
  24. #define CFM_AddressIsResolved_(addr)    ((addr) != (void*) kUnresolvedCFragSymbolAddress)
  25.  
  26. extern    usbKeyboardPBStruct myKeyboardPB;
  27. extern    usbKeyboardPBStruct shimKeyboardPB;
  28.  
  29. void GetKeysPressed(USBHIDData * pKeysPressed);
  30.  
  31. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  32. {
  33.     myKeyboardPB.interruptRefcon = refcon;
  34.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  35.     return 0;
  36. }
  37.  
  38. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  39. {
  40.     switch (theControlSelector)
  41.     {
  42.         case kHIDSetLEDStateByBits:
  43.             if (shimKeyboardPB.keyboardReady)
  44.             {
  45.                 shimKeyboardPB.keyboardReady = false;    // Don't do this again before it completes
  46.                 shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  47.     
  48.                 shimKeyboardPB.retryCount = 3;
  49.                 shimKeyboardPB.delayLevel = 0;                            
  50.                 shimKeyboardPB.transDepth = 0;    
  51.                 
  52.                 shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  53.                 KeyboardInitiateTransaction(&shimKeyboardPB.pb);
  54.             }
  55.             else
  56.             {
  57.                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Set LED request when keyboard is busy", myKeyboardPB.interfaceRef);
  58.                 return kUSBDeviceBusy;
  59.             }
  60.             break;
  61.             
  62.         case kHIDRemoveInterruptHandler:
  63.             myKeyboardPB.interruptRefcon = nil;
  64.             myKeyboardPB.pSavedInterruptRoutine = nil;
  65.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  66.             break;
  67.             
  68.         case kHIDEnableDemoMode:
  69.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Enabled", myKeyboardPB.interfaceRef);
  70.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  71.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  72.             break;
  73.  
  74.         case kHIDDisableDemoMode:
  75.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Disabled", myKeyboardPB.interfaceRef);
  76.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  77.             break;
  78.  
  79.         default:
  80.             return paramErr;
  81.     }
  82.     return 0;
  83. }
  84.  
  85. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  86. {
  87. UInt8    i,keycount;
  88.     
  89.     keycount = 0;
  90.     for (i = 0; i < kKeyboardModifierBits; i++)
  91.     {
  92.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  93.         {
  94.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  95.         }
  96.     }
  97.             
  98.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  99.     {
  100.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  101.         {
  102.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  103.             {
  104.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  105.             }
  106.         }                                                        
  107.     }
  108.     pKeysPressed->kbd.keycount = keycount;
  109. }
  110.  
  111.  
  112. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  113. {
  114. HIDInterruptProcPtr * pHIDIntProcPtr;
  115. UInt32 * pInterruptRefcon;
  116.  
  117.     switch (theInfoSelector)
  118.     {
  119.         case kHIDGetCurrentKeys:
  120.             GetKeysPressed((USBHIDDataPtr)theInfo);
  121.             break;
  122.  
  123.         case kHIDGetInterruptHandler:
  124.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  125.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  126.             break;
  127.  
  128.         case kHIDGetInterruptRefcon:
  129.             pInterruptRefcon = (UInt32 *)theInfo;
  130.             *pInterruptRefcon = myKeyboardPB.interruptRefcon;
  131.             break;
  132.         
  133.         default:
  134.             return paramErr;
  135.     }
  136.     return 0;
  137. }
  138.  
  139. OSStatus USBHIDPollDevice(void)
  140. {
  141. #ifndef DDKBuild
  142.     USLPolledProcessDoneQueue();
  143. #endif
  144.     return kUSBNoErr;
  145. }
  146.  
  147. OSStatus USBHIDEnterPolledMode(void)
  148. {    
  149. #ifndef DDKBuild
  150.     USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Entering Polled Mode: ", 0);
  151.     if ( CFM_AddressIsResolved_(USLDebuggerActive) )
  152.         USLDebuggerActive( true );
  153. #endif
  154.     return kUSBNoErr;
  155. }
  156.  
  157. OSStatus USBHIDExitPolledMode(void)
  158. {
  159. #ifndef DDKBuild
  160.     USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Exiting Polled Mode: ", 0);
  161.     if ( CFM_AddressIsResolved_(USLDebuggerActive) )
  162.         USLDebuggerActive( false );
  163. #endif
  164.     return kUSBNoErr;
  165. }
  166.  
  167. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  168. {
  169. #pragma unused (devicetype)
  170. static    UInt8    keydebug = 0;
  171.  
  172. UInt8    i, j, newkey, oldkey, deltas;
  173.  
  174. UInt8        changedmodifiers, keycount;
  175. USBHIDData    theKeyboardData;
  176. Boolean        keypressedflag, keyreleasedflag;
  177.     
  178.     deltas = 0;
  179.     
  180.     if (myKeyboardPB.hidEmulationInit == false)
  181.     {
  182.         myKeyboardPB.hidEmulationInit = true;
  183.         for (i = 0; i < kKeyboardReportSize; i++)
  184.             myKeyboardPB.oldHIDReport[i] = 0;
  185.     };
  186.     
  187.     myKeyboardPB.oldHIDReport[1] = 0x0;
  188.     hidReport[1] = 0x0;
  189.     
  190.     for (i = 0; i < kKeyboardReportSize; i++)
  191.     {
  192.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  193.         {
  194.             deltas++;
  195.         }
  196.     }
  197.     
  198.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  199.     {
  200.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  201.     }
  202.     else
  203.     {
  204.         if (deltas)
  205.         {
  206.             keycount = 0;
  207.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  208.             
  209.             if (changedmodifiers)
  210.             {
  211.                 for (i = 0; i < kKeyboardModifierBits; i++)
  212.                 {
  213.                     if (changedmodifiers & (1 << i))
  214.                     {
  215.                         if (hidReport[0] & (1 << i))
  216.                         {
  217.                             if (keydebug++ < 8)
  218.                             {
  219.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key pressed: ", (0xe0 + i));
  220.                             }
  221.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  222.                         }
  223.                         else
  224.                         {
  225.                             if (keydebug++ < 8)
  226.                             {
  227.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key released:", (0xe0 + i));
  228.                             }
  229.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  230.                         }
  231.                     }
  232.                 }
  233.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  234.             }
  235.             
  236.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  237.             {
  238.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  239.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  240.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  241.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  242.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  243.                 // would have otherwise resulted in multiple events in a single report".
  244.                 
  245.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  246.                 // check all the old keys against all the new keys...
  247.                 
  248.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  249.                 {
  250.                     keypressedflag = true;
  251.                     newkey = hidReport[i];
  252.                     
  253.                     keyreleasedflag = true;
  254.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  255.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  256.                     {                                    
  257.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  258.                         {                                
  259.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  260.                         }
  261.                         
  262.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  263.                         {                                
  264.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  265.                         }
  266.                     }
  267.                     if ((newkey > 0x03) && keypressedflag)
  268.                     {
  269.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  270.                     }
  271.                     
  272.                     if ((oldkey > 0x03) && keyreleasedflag)
  273.                     {
  274.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  275.                     }
  276.                     
  277.                     if (keycount > 20)                                    // a worse case scenario is:
  278.                     {                                                    // 4 modifier keys up
  279.                         break;                                            // the other 4 modifier keys down
  280.                     }                                                    // 6 previously reported keys up
  281.                 }                                                        // 6 newly reported keys down
  282.                                                                         // 6 + 6 + 4 + 4 = 20
  283.                 for (i = 0; i<kKeyboardReportSize; i++)
  284.                 {
  285.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  286.                 };
  287.             }
  288.             
  289.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  290.             {
  291.                 theKeyboardData.kbd.keycount = keycount;
  292.                 (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
  293.             }
  294.         }
  295.     }
  296. }
  297.  
  298.  
  299. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  300. {
  301.     (UInt32)kHIDStandardDispatchVersion,
  302.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  303.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  304.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  305.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  306.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  307.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  308. };
  309.